import 'dart:convert';
import 'dart:typed_data';

import 'package:encrypt/encrypt.dart';
import 'package:lib_common/lib_common.dart';
import 'package:pointycastle/export.dart';

extension StringExtension on String {
  /// 自动换行
  ///
  /// 处理String文字自动换行问题
  /// 对特殊字符使用时可能出现问题待额外处理
  String get autoLine {
    return Characters(this).join('\u{200B}');
  }
}

class StringUtils {
  StringUtils._();

  static final RegExp phoneRegExp = RegExp(r'^1[3456789]\d{9}$');

  static bool match(RegExp regExp, String str) {
    return regExp.hasMatch(str);
  }

  static const String publicKey = "-----BEGIN PUBLIC KEY-----\n"
      "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgHS/tusMnaZ8NGJsZ/"
      "aIeKNGHR7TxAsSessDQ1R9Cq633WlJQaDRSjCcXcHqddt01nyRdO/l6QM6"
      "fA2433hZpMhEcU0BAuulZR9v8NHem3I4O9Ms+2RDIfIKhCLw0gwyJPORgX"
      "ybs6TtPEPO9SRGomENM61UWkXbiR2bfE4F07QIDAQAB\n"
      "-----END PUBLIC KEY-----";

  static bool isMobile(String text) {
    return phoneRegExp.hasMatch(text.trim());
  }

  static String getPerTimePrice(double? price, int? addTimeSecond) {
    var result = "0.0";
    if (price != null && addTimeSecond != null && addTimeSecond != 0) {
      var rational = Decimal.parse("$price") * Decimal.fromInt(60) * Decimal.fromInt(60) / Decimal.fromInt(addTimeSecond);
      result = rational.toDouble().toStringAsFixed(1);
    }
    return result;
  }

  static String toStar(String? text) {
    return text?.replaceAll(RegExp(r'.'), "*") ?? "";
  }

  static String rsaEncrypt(String? text) {
    if (text?.isEmpty ?? true) {
      return "";
    }
    return encryptRSA(text!);
  }

  static Uint8List concatenateBytes(List<Uint8List> byteList) {
    int totalLength = byteList.fold(0, (sum, bytes) => sum + bytes.length);
    Uint8List result = Uint8List(totalLength);
    int offset = 0;

    for (var bytes in byteList) {
      result.setRange(offset, offset + bytes.length, bytes);
      offset += bytes.length;
    }

    return result;
  }

  static String encryptRSA(String plaintext) {
    try {
      final cipher = PKCS1Encoding(RSAEngine())..init(true, PublicKeyParameter<RSAPublicKey>(RSAKeyParser().parse(publicKey) as RSAPublicKey));

      final utf8Bytes = Uint8List.fromList(utf8.encode(plaintext));
      final inputLen = utf8Bytes.length;
      int offLen = 0;
      int i = 0;
      List<Uint8List> bops = [];

      while (inputLen - offLen > 0) {
        final chunkSize = (inputLen - offLen > 117) ? 117 : inputLen - offLen;
        final cache = cipher.process(Uint8List.sublistView(utf8Bytes, offLen, offLen + chunkSize));
        bops.add(cache);
        i++;
        offLen = 117 * i;
      }

      final encryptedData = concatenateBytes(bops);
      final base64Encoded = base64Encode(encryptedData);

      return base64Encoded;
    } catch (e) {
      LogUtils.e("$e");
      return "";
    }
  }
}
